﻿namespace NJQuery {
	using System;
	using System.ComponentModel;
	using System.Web.UI;
	using System.Diagnostics.CodeAnalysis;

	/// <summary>
	/// Defines a jQuery UI <see cref="Dialog"/> widget button.
	/// </summary>
	public class DialogButton : DialogButtonBase, IPostBackEventHandler {


		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="DialogButton"/> class.
		/// </summary>
		public DialogButton() { }

		#endregion


		#region Properties

		/// <summary>
		/// Gets or sets the client JavaScript executed when the button is clicked.
		/// </summary>
		[DefaultValue(""), Category("Behavior")]
		public virtual string OnClientClick {
			get { return ViewState["OnClientClick"] as string ?? string.Empty; }
			set { ViewState["OnClientClick"] = value; }
		}

		/// <summary>
		/// Gets or sets whether or not the button performs a client-side close of the dialog.
		/// </summary>
		[DefaultValue(false), Category("Behavior")]
		public virtual bool CloseDialog {
			get { return ViewState["CloseDialog"] as bool? ?? false; }
			set { ViewState["CloseDialog"] = value; }
		}

		/// <summary>
		/// Gets or sets whether or not the button will post back to the server when clicked.
		/// </summary>
		[DefaultValue(false), Category("Behavior")]
		public virtual bool PostBackOnClick {
			get { return ViewState["PostBackOnClick"] as bool? ?? false; }
			set { ViewState["PostBackOnClick"] = value; }
		}

		#endregion


		#region Events

		/// <summary>
		/// Occurs when the button is clicked.
		/// This event requires the <see cref="PostBackOnClick" /> property to have a value of True.
		/// </summary>
		[Category("Action")]
		public event EventHandler Click;

		#endregion


		#region Methods: Event hooks

		/// <summary>
		/// Raises the <see cref="Click"/> event.
		/// </summary>
		/// <param name="e">The <see cref="EventArgs"/> object that contains the event data.</param>
		protected virtual void OnClick(EventArgs e) {
			if(Click != null) Click.Invoke(this, e);
		}

		#endregion


		#region Methods: Render hooks

		/// <summary>
		/// Renders the client click script for the button.
		/// This method is used primarily by control developers.
		/// </summary>
		/// <param name="script">A <see cref="ScriptBuilder"/> that creates the output stream to render jQuery JavaScript on the client.</param>
		protected override void RenderOnClickScript(ScriptBuilder script) {

			bool postBackOnClick = PostBackOnClick;
			bool closeDialog = CloseDialog;
			string onClientClick = OnClientClick;

			// Custom Code Only
			if(!postBackOnClick && !closeDialog) {
				if(!string.IsNullOrEmpty(onClientClick))
					script.Append(onClientClick);
				return;
			}

			string uniqueID = UniqueID;

			script.Append("function() {");

			script.Indent++;

			// Render OnClientClick
			if(!string.IsNullOrEmpty(onClientClick)) {

				script.NewLine();
				script.Append("var onClick = ");
				script.Append(onClientClick);
				script.Append(";");

				script.NewLine();
				script.Append("if(onClick() == false) return;");

			}

			//TODO: There's bound to be a conflict here if ther is postback on close
			//Close the dialog
			if(closeDialog) {
				script.NewLine();
				script.Append("$(this).dialog('close');");
			}

			//Perform the postback
			if(postBackOnClick) {
				script.NewLine();
				script.Append("__doPostBack("); //TODO: Decide if there is some delegate way to as .NET for the postback function and still generate code in event argument
				script.AppendValue(uniqueID);
				script.Append(", '');");
			}

			script.Indent--;
			script.NewLine();

			script.Append("}");

			//Register for event validation
			if(postBackOnClick) Page.ClientScript.RegisterForEventValidation(uniqueID);

		}

		#endregion


		#region Methods: Post Event

		/// <summary>
		/// Enables a server control to process an event raised when a form is posted to the server.
		/// </summary>
		/// <param name="eventArgument">A <see cref="String"/> that represents an optional event argument to be passed to the event handler.</param>
		[SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "This method is amazing.  You get a complaint if you don't include the protected one, but when you do, it tells you to use events.  I included it simply because it gives the derrived control a chance to hook deeper.")]
		protected virtual void RaisePostBackEvent(string eventArgument) {

			Page.ClientScript.ValidateEvent(UniqueID, eventArgument);

			OnClick(EventArgs.Empty);

		}

		#endregion


		#region Explicit Implementation: IPostBackEventHandler

		void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
			RaisePostBackEvent(eventArgument);
		}

		#endregion


	}

}